<?php

/**
 * 
 * 身份加密验证类
 * @example
 * $id = 11; //当前ID
 * 加密步骤：
 * $encrypted = SCS::identify()->setID($id);
 * SCS::cookie()->set('id', $encrypted);
 * 解密步骤：
 * if(SCS::identity()->checkValid($encrpted)) { //检查通行证是否合法
 *     SCS::identity()->getID($encrpt_str); // 结果为11
 * }
 * @author keluo<pycorvn@yeah.net>
 * @since 2015-01-24
 */

class SCIdentity {
    
    /**
     * 检查当前加密字符串是否合法
     * @param string $string
     * @param boolean $returnResult 是否返回解密串
     * @return mixed
     */
    public function checkValid($string, $returnResult = true) {
        $decrypt = $this->decrypt($string);
        $decrypt = explode('|', $decrypt);
        if(intval($decrypt[0]) <= 0) { //检查ID合法性
            return false;
        }
        if(!isset($decrypt[1])) { //是否包含第二个元素(第一个元素为ID，第二个元素为IP)
            return false;
        }
        
        if($this->getClientIP() != $decrypt[1]) { //检查IP是否相等
            return false;
        }
        
        return $returnResult ? $decrypt[0] : true;  
    }
    
    /**
     * 
     * 加密唯一标识ID
     * @param string 唯一标识$id
     * @return 加密后的字符串
     */
    public function setID($id) {
        return $this->encrypt($id.'|'.$this->getClientIP());
    }
    
    /**
     * 获取当前已加密过的字符串中隐含的ID
     * @return string 唯一标识ID
     */
    public function getID($string) {
        $decrypt = $this->decrypt($string);
        $decrypt = explode('|', $decrypt);
        if(!isset($decrypt[0])) {
            return false; 
        }
        return $decrypt[0];
    }
    
    private function getKey() {
        if(!SCS::config()->id_key) throw new Exception('请在配置文件'.SC_CONFIG_PATH.'/config.php 中配置"id_key"的值');
        return SCS::config()->id_key;    
    }
    
    /**
     * 返回以当前用户ID、IP经系统加密函数加密后的字符串
     * @param integer $id 唯一标识ID
     * @return string 加密后的字符串
     */
    private function encrypt($text) {
        srand((double)microtime() * 1000000);
        $encrypt_key = md5(rand(0, 32000));
        $ctr = 0;
        $tmp = '';
        for($i = 0; $i < strlen($text); $i++) {
            if($ctr == strlen($encrypt_key)) $ctr = 0;
            $tmp .= substr($encrypt_key, $ctr, 1).(substr($text, $i, 1) ^ substr($encrypt_key, $ctr, 1));
            $ctr++;
        }
        return base64_encode($this->keyED($tmp));
    }
    
    /**
     * 字符串解密
     * @param string $text 加密字符串
     * @return 解密后的字符串
     */
    private function decrypt($text) {
        $text = $this->keyED(base64_decode($text));
        $tmp = '';
        for($i = 0; $i < strlen($text); $i++) {
            $md5 = substr($text, $i, 1);
            $i++;
            $tmp .= (substr($text, $i, 1) ^ $md5);
        }
        return $tmp;
    }
    
    private function keyED($text) {
        $encrypt_key = md5($this->getKey());
        $ctr = 0;
        $tmp = '';
        for($i = 0; $i < strlen($text); $i++) {
            if($ctr == strlen($encrypt_key)) $ctr=0;
            $tmp .= substr($text, $i, 1) ^ substr($encrypt_key, $ctr, 1);
            $ctr++;
        }
        return $tmp;
    }
    
    /**
     * 
     * 返回当前连接的客户端IP
     * @return string IP地址
     */
    private function getClientIP() {
        if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } elseif(isset($_SERVER['HTTP_CLIENT_IP'])) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } else {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        return preg_match('/[\d\.]{7,15}/', $ip, $matches) ? $matches[0] : 'unknown';
    }
}